package com.med.service;


import com.med.entity.DoctorDO;
import com.med.entity.ScheduleDO;
import com.med.mapper.GenerateNumberMapper;
import com.med.mapper.NotificationMapper;
import com.med.mapper.ScheduleMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import java.sql.Date;
import java.sql.Time;
import java.sql.Timestamp;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

/**
 * @BelongsProject: Internet-based-healthcare
 * @BelongsPackage: com.med.service
 * @Author: 小龚
 * @CreateTime: 2025-08-22 15:51
 * @Description: 智能排班
 * @Version: 1.0
 */
@Service
public class ScheduleService {

    private final ScheduleMapper scheduleMapper;


    private final GenerateNumberMapper numberMapper;

    private final NotificationMapper notificationMapper;


    @Autowired
    public ScheduleService(ScheduleMapper scheduleMapper, GenerateNumberMapper numberMapper, NotificationMapper notificationMapper) {
        this.scheduleMapper = scheduleMapper;
        this.numberMapper = numberMapper;
        this.notificationMapper = notificationMapper;

    }


    // 获取所有医生的id
    public List<Integer> getDoctorId() {
        List<DoctorDO> list = scheduleMapper.findAllDoctor();
        List<Integer> ids = new ArrayList<>();
        for (DoctorDO doctorDO : list) {
            ids.add(doctorDO.getDoctorId());
        }
        return ids;
    }

    public void initialScheduleDoctorsWeekly(List<Integer> doctorIds) {
        LocalDate startDate = LocalDate.now().plusDays(1);
        for (Integer doctorId : doctorIds) {
            scheduleForNextWeek(doctorId, startDate);
        }
    }

    private void scheduleForNextWeek(Integer doctorId, LocalDate startDate) {
        for (int i = 0; i < 7; i++) {
            LocalDate date = startDate.plusDays(i + 2);
            createSchedule(doctorId, date);
        }
    }

    // 检查医生的排班
    @Scheduled(cron = "0 0 12 * * ?")
    public void checkScheduleForDoctor() {
        System.out.println("执行了 ~~~~");
        String status = scheduleMapper.schedulingStatus();
        System.out.println(status);
        if (Objects.equals(status, "1")) {
            System.out.println("智能排班已关闭");
            return;
        }
        System.out.println("智能排班已开启");
        List<Integer> doctorIds = getDoctorId();
        for (Integer doctorId : doctorIds) {
            List<ScheduleDO> scheduleDOList = scheduleMapper.findDoctorByDoctorId(doctorId);
            if (hasTwoDaysLeft(scheduleDOList)) {
                LocalDate startDate = LocalDate.now().plusDays(1);
                scheduleForNextWeek(doctorId, startDate);

            }
        }
        generateReservationNumber();
        generateNotice();
    }

    // 生成医生的预约号
    public void generateReservationNumber() {
        List<Integer> doctorId = getDoctorId();
        // 存放需要插入的所有时间段
        List<Map<String, Object>> slots = new ArrayList<>();
        for (Integer docId : doctorId) {
            List<ScheduleDO> schedules = numberMapper.getScheduleByDoctorId(docId);
            for (ScheduleDO schedule : schedules) {
                Date date = schedule.getScheduleDate();
                Time startTime = schedule.getScheduleStartTime();
                Time endTime = schedule.getScheduleEndTime();
                LocalDate localDate = date.toLocalDate();
                LocalTime startTimeLocalTime = startTime.toLocalTime();
                LocalTime endTimeLocalTime = endTime.toLocalTime();
                LocalDateTime localStartTime = LocalDateTime.of(localDate, startTimeLocalTime);
                LocalDateTime localEndTime = LocalDateTime.of(localDate, endTimeLocalTime);
                // 循环生成每 30 分钟的时间段
                LocalDateTime slotStart = localStartTime;
                while (slotStart.isBefore(localEndTime)) {
                    Timestamp startTimestamp = Timestamp.valueOf(slotStart);
                    Map<String, Object> map = new HashMap<>();
                    map.put("doctorId", docId);
                    map.put("startTime", startTimestamp);
                    map.put("scheduleDate", date);
                    slots.add(map);
                    slotStart = slotStart.plusMinutes(30);
                }
            }
        }
        if (!slots.isEmpty()) {
            numberMapper.generateNumber(slots);
            numberMapper.updateSign(slots);
            generateNotice();
        }
    }


    private void createSchedule(Integer doctorId, LocalDate date) {
        ScheduleDO scheduleDO = new ScheduleDO();
        scheduleDO.setDocId(doctorId);
        scheduleDO.setScheduleDate(java.sql.Date.valueOf(date));
        scheduleDO.setScheduleStartTime(Time.valueOf(LocalTime.of(8, 30)));
        scheduleDO.setScheduleEndTime(Time.valueOf(LocalTime.of(12, 0)));
        scheduleMapper.schedule(scheduleDO);

        scheduleDO.setScheduleStartTime(Time.valueOf(LocalTime.of(14, 0)));
        scheduleDO.setScheduleEndTime(Time.valueOf(LocalTime.of(17, 30)));
        scheduleMapper.schedule(scheduleDO);
    }


    public boolean hasTwoDaysLeft(List<ScheduleDO> list) {
        LocalDate today = LocalDate.now();
        long count = 0;
        for (ScheduleDO scheduleDO : list) {
            java.sql.Date scheduleDate = scheduleDO.getScheduleDate();
            if (scheduleDate != null) {
                try {
                    LocalDate localDate = toLocalDate(scheduleDate);
                    if (localDate.isAfter(today)) {
                        count++; // 计数符合条件的日期
                    }
                } catch (Exception e) {
                    System.err.println("转换日期时出错: " + scheduleDate);
                    e.printStackTrace(); // 打印异常信息
                }
            }
        }
        System.out.println("数量：" + count);
        return count == 4 || count == 0;
    }

    private LocalDate toLocalDate(Date date) {
        return LocalDate.of(date.toLocalDate().getYear(), date.toLocalDate().getMonth(), date.toLocalDate().getDayOfMonth());
    }

    // 获取智能排班状态
    public String getScheduleStatus() {
        return scheduleMapper.schedulingStatus();
    }

    // 更改智能排班状态
    public Integer updateSchedulingStatus() {
        Integer count = scheduleMapper.updateSchedulingStatus();
        checkScheduleForDoctor();
        return count;
    }


    // 生成消息通知
    public void generateNotice() {
        // 获取未生成消息通知的排班
        List<ScheduleDO> schedule = notificationMapper.getSchedule();
        if (!schedule.isEmpty()) {
            // 获取为生成消息通知的排班的医生的id
            for (ScheduleDO scheduleDO : schedule) {
                insertNotice(scheduleDO);
            }
            System.out.println("有未消息通知的排班");
        }
    }

    // 插入消息通知
    private void insertNotice(ScheduleDO scheduleDO) {
        System.out.println("医生id" + scheduleDO.getDocId());
        // 获取医生的医生
        String doctorName = notificationMapper.getDoctorNameByDocId(scheduleDO.getDocId());
        System.out.println(doctorName);
        // 获取医生的部门
        String departmentName = notificationMapper.getDepartmentNameByDocId(scheduleDO.getDocId());
        System.out.println(departmentName);
        String content = departmentName + "的" + doctorName + "医生您于 " + scheduleDO.getScheduleDate() + " " + scheduleDO.getScheduleStartTime() + "-" + scheduleDO.getScheduleEndTime() + "有排班，请注意时间安排";
        // 插入数据
        notificationMapper.insertNotice(scheduleDO, content);
        // 更改消息生成的状态为已生成
        notificationMapper.updateNoticeStatus(scheduleDO);
    }


    // 修改排班时排班的是否已生成预约号是否已生成消息通知都需要修改成否
    public void updateSchedule(Integer doctorId, Integer scheduleId) {
        notificationMapper.updateSchedule(doctorId, scheduleId);
    }

    // 修改排班之后删除生成的预约号以及生成的消息通知记录
    public void delAppointmentAndNotice(Integer doctorId, Integer scheduleId, String date) {
        String startTime = date + " 00:00:00";
        String endTime = date + " 23:59:59";
        // 定义日期时间格式
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        // 转换
        LocalDateTime startDateTime = LocalDateTime.parse(startTime, formatter);
        LocalDateTime endDateTime = LocalDateTime.parse(endTime, formatter);
        // 格式化为字符串以便用于 SQL
        String formattedStartTime = startDateTime.format(formatter);
        String formattedEndTime = endDateTime.format(formatter);
        System.out.println("开始时间" + startTime);
        System.out.println(endTime);
        // 删除预约号
        Integer count = notificationMapper.deleteAppointment(doctorId, formattedStartTime, formattedEndTime);
        System.out.println("数量" + count);
        // 删除消息通知记录
        notificationMapper.deleteNotice(scheduleId);
    }
}
